package cn.stylefeng.guns.modular.storage.service.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.stylefeng.guns.base.pojo.page.LayuiPageFactory;
import cn.stylefeng.guns.base.pojo.page.LayuiPageInfo;
import cn.stylefeng.guns.modular.basic.entity.BasicGoods;
import cn.stylefeng.guns.modular.basic.model.params.BasicPositionParam;
import cn.stylefeng.guns.modular.basic.model.params.BasicPrivatecarParam;
import cn.stylefeng.guns.modular.basic.model.params.BasicTrayParam;
import cn.stylefeng.guns.modular.basic.model.result.BasicPositionResult;
import cn.stylefeng.guns.modular.basic.model.result.BasicPrivatecarResult;
import cn.stylefeng.guns.modular.basic.model.result.BasicTrayResult;
import cn.stylefeng.guns.modular.basic.service.BasicGoodsService;
import cn.stylefeng.guns.modular.basic.service.BasicPositionService;
import cn.stylefeng.guns.modular.basic.service.BasicTrayService;
import cn.stylefeng.guns.modular.order.model.params.OrderPutParam;
import cn.stylefeng.guns.modular.order.model.params.OrderTransportDetailedParam;
import cn.stylefeng.guns.modular.order.model.params.OrderTransportParam;
import cn.stylefeng.guns.modular.order.model.result.OrderPutResult;
import cn.stylefeng.guns.modular.order.model.result.OrderTransportDetailedResult;
import cn.stylefeng.guns.modular.order.model.result.OrderTransportResult;
import cn.stylefeng.guns.modular.order.service.OrderPutService;
import cn.stylefeng.guns.modular.storage.entity.StoragePut;
import cn.stylefeng.guns.modular.storage.entity.StoragePutSingle;
import cn.stylefeng.guns.modular.storage.entity.StorageStock;
import cn.stylefeng.guns.modular.storage.mapper.StoragePutMapper;
import cn.stylefeng.guns.modular.storage.model.params.StoragePutParam;
import cn.stylefeng.guns.modular.storage.model.params.StoragePutSingleParam;
import cn.stylefeng.guns.modular.storage.model.params.StorageStockParam;
import cn.stylefeng.guns.modular.storage.model.result.StoragePutResult;
import cn.stylefeng.guns.modular.storage.model.result.StoragePutSingleResult;
import cn.stylefeng.guns.modular.storage.model.result.StorageStockResult;
import cn.stylefeng.guns.modular.storage.service.StoragePutService;
import cn.stylefeng.guns.modular.storage.service.StoragePutSingleService;
import cn.stylefeng.guns.modular.storage.service.StorageStockDetailedService;
import cn.stylefeng.guns.modular.storage.service.StorageStockService;
import cn.stylefeng.guns.modular.transport.model.params.TDispatchParam;
import cn.stylefeng.guns.modular.transport.model.params.TransportDispatchParam;
import cn.stylefeng.guns.modular.transport.model.params.TransportReceiptParam;
import cn.stylefeng.guns.modular.transport.model.result.TDispatchResult;
import cn.stylefeng.guns.modular.transport.model.result.TransportDispatchResult;
import cn.stylefeng.guns.modular.transport.model.result.TransportReceiptResult;
import cn.stylefeng.guns.sys.modular.system.entity.User;
import cn.stylefeng.roses.core.reqres.response.ResponseData;
import cn.stylefeng.roses.core.util.ToolUtil;

/**
 * 入库单表 服务实现类
 */
@Service
public class StoragePutServiceImpl extends ServiceImpl<StoragePutMapper, StoragePut> implements StoragePutService {

    @Resource
    private OrderPutService orderPutService;

    @Resource
    private StoragePutSingleService storagePutSingleService;

    @Resource
    private StorageStockService storageStockService;

    @Resource
    private BasicTrayService basicTrayService;

    @Override
    public void add(StoragePutParam param){
        StoragePut entity = getEntity(param);
        this.save(entity);
    }

    @Override
    public void delete(StoragePutParam param){
        this.removeById(getKey(param));
    }

    @Override
    public void update(StoragePutParam param){
        StoragePut oldEntity = getOldEntity(param);
        StoragePut newEntity = getEntity(param);
        ToolUtil.copyProperties(newEntity, oldEntity);
        this.updateById(newEntity);
    }

    @Override
    public StoragePutResult findBySpec(StoragePutParam param){
        return this.baseMapper.findBySpec(param);
    }

    @Override
    public List<StoragePutResult> findListBySpec(StoragePutParam param){
        return null;
    }

    @Override
    public LayuiPageInfo findPageBySpec(StoragePutParam param,String condition,Long deptId,Long operateId){
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.customPageList(pageContext, param,condition,deptId,operateId);
        return LayuiPageFactory.createPageInfo(page);
    }

    private Serializable getKey(StoragePutParam param){
        return param.getId();
    }

    private Page getPageContext() {
        return LayuiPageFactory.defaultPage();
    }

    private StoragePut getOldEntity(StoragePutParam param) {
        return this.getById(getKey(param));
    }

    private StoragePut getEntity(StoragePutParam param) {
        StoragePut entity = new StoragePut();
        ToolUtil.copyProperties(param, entity);
        return entity;
    }

	@Override
	public StoragePut findByThelastone() {
		return this.baseMapper.findByThelastone();
	}

    @Override
    public LayuiPageInfo findPageBySpecANDNUM(StoragePutParam param, String condition,Long deptId) {

        Page pageContext = getPageContext();
        IPage page = this.baseMapper.customPageListANDNUM(pageContext, param,condition,deptId);

        return LayuiPageFactory.createPageInfo(page);
    }

	@Override
	public LayuiPageInfo findPageBySpecStorageList(StoragePutParam param,Long deptId) {

        Page pageContext = getPageContext();
        IPage page = this.baseMapper.findPageBySpecStorageList(pageContext,param,deptId);

        return LayuiPageFactory.createPageInfo(page);
	}

	@Override
	public List<StoragePutResult> findPageBySpecStorageListNew(StoragePutParam param,Long deptId,Long operateId) {
        return this.baseMapper.findPageBySpecStorageListNew(param,deptId, operateId);
	}

	@Resource
    private BasicGoodsService basicGoodsService;

	/**
	 * 入库复核
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResponseData confirm(StoragePutParam p,User user) {
		//更新 入库单状态
		StoragePutResult spr = findBySpec(p);
		if("COMPLETED".equals(spr.getBillstate())){
            return ResponseData.error("This inbound order has been completed!");
        } else {
            StoragePutSingleParam spsP = new StoragePutSingleParam();
            spsP.setStorageNumber(p.getStorageNumber());
            List<StoragePutSingleResult> spsrlist1 = storagePutSingleService.findListBySpecGroupByGoodsid(spsP);
            for (StoragePutSingleResult r : spsrlist1) {
            	QueryWrapper<StoragePutSingle> queryWrapper = new QueryWrapper<StoragePutSingle>();//查询是否有未入
            	queryWrapper.ne("single_state", "PENDING_APPROVAL");
            	queryWrapper.eq("goods_id", r.getGoodsId());
            	queryWrapper.eq("storage_number", r.getStorageNumber());
        		int count = storagePutSingleService.count(queryWrapper);
        		if(count > 0) {
        			continue;
        		} 
            	//更新库存状态  为在库’
        		spsP.setGoodsId(r.getGoodsId());
            	List<StoragePutSingleResult> spsrlist = storagePutSingleService.findListBySpec(spsP);//订单明细
            	List<StorageStock> ssList = new ArrayList<StorageStock>();
                StoragePutSingleParam update = new StoragePutSingleParam();
            	BasicPositionParam bpp = new BasicPositionParam();//库位输入类
            	for (StoragePutSingleResult spsr : spsrlist) {
                	if(spsr.getSingleState().equals("PENDING_APPROVAL")) {
                		StorageStock ssr = storageStockService.getById(spsr.getStockId());
                		BigDecimal as = new BigDecimal(0);
                		BigDecimal realNum = new BigDecimal(spsr.getRealNum());//实际数
                		BigDecimal num = new BigDecimal(ssr.getNum());//库存数
                		//判断 实际数 是否为0
                		if (realNum.compareTo(as)==0) {
                			//删除库存
                			StorageStockParam sspp = new StorageStockParam();
                			sspp.setId(ssr.getId());
                			storageStockService.delete(sspp);
                			//更新托盘
                			BasicTrayParam btp = new BasicTrayParam();
                			btp.setId(Integer.parseInt(ssr.getTrayId().toString()));
                			btp.setTrayState("IDLE");
                			basicTrayService.update(btp);
                		} else {
                			//判断 实际入库数量 是否和库存数一致
                			if (realNum.compareTo(num)!=0) {
                				BasicGoods basicGoods = basicGoodsService.getById(spsr.getGoodsId());
                				BigDecimal unitprice = new BigDecimal(basicGoods.getGoodsCharging());//单价
                				BigDecimal v = new BigDecimal(basicGoods.getGoodsVolume());
                				BigDecimal w = new BigDecimal(basicGoods.getGoodsWeight());
                				
                				//重新计算 体积，重量，金额
                				ssr.setNum(realNum.toString());
                				ssr.setBalenum(realNum.toString());
                				ssr.setCanNum(realNum.toString());
                				ssr.setStockWeight(w.multiply(realNum).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                				ssr.setStockVolume(v.multiply(realNum).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                				ssr.setStockMoney(unitprice.multiply(realNum).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
                			}
                			
                			bpp.setPositionNumber(spsr.getPositionNumber());
                			bpp.setDeliverId(ssr.getDeliverId());
                			bpp.setWarehouseId(Integer.parseInt(ssr.getWarehouseId().toString()));
                			BasicPositionResult bpr = basicPositionService.findBySpec(bpp,ssr.getDeptId(),user.getOperateId());//库位信息
                			ssr.setPositionId(Long.parseLong(bpr.getId().toString()));
                			ssr.setPositionNumber(spsr.getPositionNumber());
                			ssr.setAreaId(Long.parseLong(bpr.getPositionAreaId().toString()));//库区id
                			ssr.setAreaNumber(bpr.getAreaNumber());//库区编号
                			
                			ssr.setStockstate("IN_STOCK");
                			ssr.setPutTime(spsr.getRecommend());
                			ssList.add(ssr);
                		}
                		update.setId(spsr.getId());
                		update.setSingleState("RECEIVED");
                		storagePutSingleService.update(update);
                		update = new StoragePutSingleParam();
                	}
            	}
                storageStockDetailedService.batchAdd("INBOUND",spr.getStorageNumber(),"INBOUND","",ssList,user);//批量新增 库存流水
                storageStockService.updateBatchList(ssList);
			}
            return ResponseData.success();
        }
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResponseData shenhegoods(StoragePutSingleParam storagePutSingleParam, User user) {
		//更新 入库单状态
		StoragePutParam p = new StoragePutParam();
		p.setStorageNumber(storagePutSingleParam.getStorageNumber());
		StoragePutResult spr = findBySpec(p);
		if("COMPLETED".equals(spr.getBillstate())){
            return ResponseData.error("This inbound order has been completed!");
        }else {
            //更新库存状态  为在库’
            List<StoragePutSingleResult> spsrlist = storagePutSingleService.findListBySpec(storagePutSingleParam);//订单明细
            List<StorageStock> ssList = new ArrayList<StorageStock>();
            StoragePutSingleParam update = new StoragePutSingleParam();
    		BasicPositionParam bpp = new BasicPositionParam();//库位输入类
            for (StoragePutSingleResult spsr : spsrlist) {
            	if(spsr.getSingleState().equals("PENDING_APPROVAL")) {
            		StorageStock ssr = storageStockService.getById(spsr.getStockId());
            		BigDecimal as = new BigDecimal(0);
            		BigDecimal realNum = new BigDecimal(spsr.getRealNum());//实际数
            		BigDecimal num = new BigDecimal(ssr.getNum());//库存数
            		//判断 实际数 是否为0
            		if (realNum.compareTo(as)==0) {
            			//删除库存
            			StorageStockParam sspp = new StorageStockParam();
            			sspp.setId(ssr.getId());
            			storageStockService.delete(sspp);
            			//更新托盘
            			BasicTrayParam btp = new BasicTrayParam();
            			btp.setId(Integer.parseInt(ssr.getTrayId().toString()));
            			btp.setTrayState("IDLE");
            			basicTrayService.update(btp);
            		} else {
            			//判断 实际入库数量 是否和库存数一致
            			if (realNum.compareTo(num)!=0) {
            				BasicGoods basicGoods = basicGoodsService.getById(spsr.getGoodsId());
            				BigDecimal unitprice = new BigDecimal(basicGoods.getGoodsCharging());//单价
            				BigDecimal v = new BigDecimal(basicGoods.getGoodsVolume());
            				BigDecimal w = new BigDecimal(basicGoods.getGoodsWeight());
            				
            				//重新计算 体积，重量，金额
            				ssr.setNum(realNum.toString());
            				ssr.setBalenum(realNum.toString());
            				ssr.setCanNum(realNum.toString());
            				ssr.setStockWeight(w.multiply(realNum).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
            				ssr.setStockVolume(v.multiply(realNum).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
            				ssr.setStockMoney(unitprice.multiply(realNum).setScale(3, BigDecimal.ROUND_HALF_DOWN).toString());
            			}
            			
            			bpp.setPositionNumber(spsr.getPositionNumber());
            			bpp.setDeliverId(ssr.getDeliverId());
            			bpp.setWarehouseId(Integer.parseInt(ssr.getWarehouseId().toString()));
            			BasicPositionResult bpr = basicPositionService.findBySpec(bpp,ssr.getDeptId(),user.getOperateId());//库位信息
            			ssr.setPositionId(Long.parseLong(bpr.getId().toString()));
            			ssr.setPositionNumber(spsr.getPositionNumber());
            			ssr.setAreaId(Long.parseLong(bpr.getPositionAreaId().toString()));//库区id
            			ssr.setAreaNumber(bpr.getAreaNumber());//库区编号
            			
            			ssr.setStockstate("IN_STOCK");
            			ssr.setPutTime(spsr.getRecommend());
            			ssList.add(ssr);
            		}
            		update.setId(spsr.getId());
            		update.setSingleState("RECEIVED");
            		storagePutSingleService.update(update);
            		update = new StoragePutSingleParam();
            	} else {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                	ResponseData.error("Inbound Detail Status Changed");
            	}
        	}
            storageStockDetailedService.batchAdd("INBOUND",spr.getStorageNumber(),"INBOUND","",ssList,user);//批量新增 库存流水
            storageStockService.updateBatchList(ssList);
            return ResponseData.success();
        }
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResponseData revokegoods(StoragePutSingleParam storagePutSingleParam, User user) {
        //查询入库单
        StoragePutParam param = new StoragePutParam();
        param.setStorageNumber(storagePutSingleParam.getStorageNumber());
        StoragePutResult putResult = this.findBySpec(param);
        if(putResult == null) {
        	ResponseData.error("No inbound order found");
        } else {
        	if(putResult.getBillstate().equals("COMPLETED")) {
        		putResult.setBillstate("INCOMPLETE");
                ToolUtil.copyProperties(putResult,param);
                this.update(param);
        	}
        }
        
		//修改入库订单状态
		OrderPutParam orderPutParam = new OrderPutParam();
		orderPutParam.setPutNumber(putResult.getPutNumber());
		OrderPutResult orderPut = orderPutService.findBySpec(orderPutParam,null);
        if(orderPut == null) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
        	ResponseData.error("No inbound order found");
        } else {
        	if(orderPut.getBillstate().equals("WAREHOUSED")) {
        		orderPut.setBillstate("PENDING_INBOUND");
                ToolUtil.copyProperties(orderPut,orderPutParam);
                orderPutService.update(orderPutParam);
        	}
        }
        
        //查询入库单明细
        List<StoragePutSingleResult> list = storagePutSingleService.findListBySpec(storagePutSingleParam);
        
        for (StoragePutSingleResult putSingleResult : list) {
			if ("RECEIVED".equals(putSingleResult.getSingleState())) {
				BigDecimal as = new BigDecimal(0);
				BigDecimal realNum = new BigDecimal(putSingleResult.getRealNum());//入库实际数量

				if(realNum.compareTo(as) == 1) {
					StorageStockParam ssp = new StorageStockParam();
					StorageStock ssr = storageStockService.getById(putSingleResult.getStockId());
					if (ssr==null) {
						TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
						return ResponseData.error("Inventory Has Changed!");
					}
					BigDecimal num = new BigDecimal(ssr.getNum());//库存数
					if ("IN_STOCK".equals(ssr.getStockstate())) {
						if (realNum.compareTo(num)!=0) {
							TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
							return ResponseData.error("Inventory Has Changed!");
						} else {
							ToolUtil.copyProperties(ssr,ssp);
	    			        storageStockDetailedService.addNewDetailed("INBOUND",putSingleResult.getStorageNumber(),"Inbound Item Reversal","",ssp,user);//新增 库存流水
							ssp.setStockstate("RECEIVED");
							storageStockService.update(ssp);//更新库存状态
						}
					}  else {
						TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
						return ResponseData.error("Inventory Has Changed!");
					}
				}
		        ToolUtil.copyProperties(putSingleResult,storagePutSingleParam);
		        storagePutSingleParam.setSingleState("PENDING_APPROVAL");
		        storagePutSingleService.update(storagePutSingleParam);//修改入库单明细
			} else {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚
                return ResponseData.error("Inbound Detail Has Changed!");
			}
		}
        return ResponseData.success();
	}

	@Resource
    private StorageStockDetailedService storageStockDetailedService;
	
	@Resource
	BasicPositionService basicPositionService;

	@Override
	public LayuiPageInfo querylistPageBySpec(StoragePutParam param, String condition, Long deptId,Long operateId,String singlePutTime) {
        Page pageContext = getPageContext();
        IPage page = this.baseMapper.querylistPageBySpec(pageContext, param,condition,deptId, operateId, singlePutTime);
        return LayuiPageFactory.createPageInfo(page);
	}

    @Override
    public StoragePutResult findSpec(StoragePutParam storagePutParam) {
        return this.baseMapper.findSpec(storagePutParam);
    }

	@Override
	public List<StoragePutResult> findPageBySpecANDNUMNew(StoragePutParam param, String condition,
			Long deptId) {
		return this.baseMapper.findPageBySpecANDNUMNew(param,condition,deptId);
	}

	@Override
	public List<StoragePutResult> findPageBySpecNew(StoragePutParam param, String condition,
			Long deptId) {
		return this.baseMapper.findPageBySpecNew(param,condition,deptId);
	}

}
